package main

import (
	"fmt"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/pelletier/go-toml"
	"io"
	"log"
	"math/rand"
	"net/http"
	"sync"
	"time"
)

var gw sync.WaitGroup
var reconnectCount int

type Config struct {
	Http struct {
		Url string `toml:"url"`
	} `toml:"http"`

	Mqtt struct {
		Broker   string   `toml:"broker"`
		Port     int      `toml:"port"`
		Username string   `toml:"username"`
		Password string   `toml:"password"`
		Topics   []string `toml:"topics"`
	} `toml:"mqtt"`
}

var config Config

func init() {
	// 读取 TOML 配置文件
	configFile := "config.toml"
	configTree, err := toml.LoadFile(configFile)
	if err != nil {
		log.Fatalf("Error loading TOML file: %v", err)
	}

	// 将 TOML 配置映射到结构体
	err = configTree.Unmarshal(&config)
	if err != nil {
		log.Fatalf("Error unmarshaling TOML file: %v", err)
	}
}

var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) {
	if reconnectCount == 0 {
		fmt.Println("MQTT首次连接成功")
	} else {
		fmt.Printf("MQTT第%d重连成功\n", reconnectCount)
		reconnectCount = 0
	}
}

var reconnectHandler mqtt.ReconnectHandler = func(client mqtt.Client, opts *mqtt.ClientOptions) {
	reconnectCount++
	fmt.Printf("MQTT开始重连,第%d次重连...\n", reconnectCount)
}

var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) {
	fmt.Printf("MQTT连接异常，异常信息：%v\n", err)
}

var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
	fmt.Printf("%v%v => %s\n", "MQTT: ", msg.Topic(), msg.Payload())
}

func testHost() {
	client := http.Client{
		Timeout: time.Second * 3, // 设置超时时间为 3 秒
	}

	response, err := client.Get(config.Http.Url)
	if err != nil {
		fmt.Println(err)
	}
	if response != nil {
		status := response.Status
		fmt.Println("HTTP:", time.Now().Format("2006-01-02 15:04:05"), "响应状态码:", status) // 获取状态码
		defer func(Body io.ReadCloser) {
			err := Body.Close()
			if err != nil {
				fmt.Println(err)
			}
		}(response.Body)
	}
}

func testMqtt() {
	var clientId = fmt.Sprintf("go_mqtt_client_%v", rand.Intn(1000))
	mqttUrl := fmt.Sprintf("tcp://%s:%d", config.Mqtt.Broker, config.Mqtt.Port)
	fmt.Printf("MQTT尝试连接服务端[%v]\n", mqttUrl)
	opts := mqtt.NewClientOptions()
	opts.AddBroker(mqttUrl)
	opts.SetClientID(clientId)
	opts.SetUsername(config.Mqtt.Username)
	opts.SetPassword(config.Mqtt.Password)
	opts.SetReconnectingHandler(reconnectHandler)
	opts.SetDefaultPublishHandler(messagePubHandler)
	opts.KeepAlive = 5
	opts.OnConnect = connectHandler
	opts.OnConnectionLost = connectLostHandler
	client := mqtt.NewClient(opts)
	token := client.Connect()
	if token.Wait() && token.Error() != nil {
		fmt.Printf("mqtt连接异常，%v", token.Error())
	} else {
		func() {
			for _, topic := range config.Mqtt.Topics {
				token := client.Subscribe(topic, 1, nil)
				token.Wait()
				fmt.Printf("Subscribed to topic %v\n", topic)
			}
		}()
		for {
			for _, topic := range config.Mqtt.Topics {
				token := client.Publish(topic, 1, false, time.Now().Format("2006-01-02 15:04:05"))
				token.Wait()
				time.Sleep(time.Second)
			}
		}
	}
}

func main() {
	gw.Add(2)

	go func() {
		for {
			time.Sleep(time.Second)
			testHost()
		}
	}()

	go testMqtt()

	gw.Wait()
}
